package com.softcits.email.service;

import org.apache.commons.mail.EmailException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Service;

import com.softcits.email.auth.SoftCitsUser;
import com.softcits.email.controller.EmailController;
import com.softcits.email.model.LoginUser;
import com.softcits.email.model.MailInfo;
import com.softcits.email.utils.ResultUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author Lan
 * @since 2019-04-04
 */
@Service
public class UserService {
    
    private final static Logger logger = LoggerFactory.getLogger(UserService.class);
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    private EmailService es;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    
    public static String[][] columnMapping = {
        {"loginName","LOGIN_NAME"},
        {"userEmail","EMAIL"},
        {"userPhone","PHONE"},
        {"userStatusDesc","STATUS"},
        {"userCreateTime","CREATION_TIME"},
    };
    
    public Long getTotals(String where) {
        String sql = String.format("select count(*) from e_user %s", where);
        Long number = this.jdbcTemplate.queryForObject(sql, Long.class);
        
        return number;
    }
    
    public SoftCitsUser updateUser(SoftCitsUser userParam) {
        String sql = "update e_user set EMAIL = ?, PHONE = ?, STATUS = ?, MODIFICATION_TIME = ?, MODIFICATION_USER= ? WHERE LOGIN_NAME = ?";
        
        Object param[] = {
                userParam.getUserEmail(),
                userParam.getUserPhone(),
                userParam.getUserStatus(),
                new Date(),
                "e_admin",
                userParam.getLoginName()
        };
        
        int updcount = this.jdbcTemplate.update(sql, param);
        
        if(updcount >= 1) {
            return userParam;
        }
        
        return null;
    }
    
    public int deleteUser(String loginName) {
        String sql = "update e_user set STATUS = ?, MODIFICATION_TIME = ?, MODIFICATION_USER= ? WHERE LOGIN_NAME = ?";
        
        Object param[] = {
                "5",
                new Date(),
                "e_admin",
                loginName
        };
        
        int updcount = this.jdbcTemplate.update(sql, param);

        return updcount;
    }
    
    public List<SoftCitsUser> list(Integer start, Integer length, String where, String order) {
        String sql = String.format("select * from e_user %s %s limit %d, %d", where, order, start, length) ;
        logger.debug("sql = " + sql);
        List<SoftCitsUser> users = this.jdbcTemplate.query(sql, new ResultSetExtractor<List<SoftCitsUser>>() {
            List<SoftCitsUser> mList = new ArrayList<>();
            @Override
            public List<SoftCitsUser> extractData(ResultSet rs) throws SQLException, DataAccessException {
                while(rs.next()) {
                    SoftCitsUser user = new SoftCitsUser();
                    user.setLoginName(rs.getString("LOGIN_NAME"));
                    user.setUserEmail(rs.getString("EMAIL"));
                    user.setUserPhone(rs.getString("PHONE"));
                    String status = rs.getString("STATUS");
                    user.setUserStatus(status);
                    user.setUserStatusDesc(getUserStatusDesc(status));
                    
                    Date date = rs.getTimestamp("CREATION_TIME");
                    String dateStr = sdf.format(date);
                    user.setUserCreateTime(dateStr);
                    mList.add(user);
                }
                return mList;
            }
            
        });
        return users;
    }

    public ResultUtil logout(HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return ResultUtil.success();
    }
    
    public SoftCitsUser getUserByLoginName(String loginName) {
        String sql = "select * from e_user where login_name = ? ";
        String args[] = {
                loginName
        };
        SoftCitsUser user = this.jdbcTemplate.query(sql, args, new ResultSetExtractor<SoftCitsUser>() {

            @Override
            public SoftCitsUser extractData(ResultSet rs) throws SQLException, DataAccessException {
                
                return userMapping(rs);
            }
            
        });
        
        return user;
    }
    
    public SoftCitsUser userMapping(ResultSet rs) throws SQLException {
        SoftCitsUser user = new SoftCitsUser();
        while(rs.next()) {
            user.setUserId(String.valueOf(rs.getInt("id")));
            user.setLoginName(rs.getString("login_name"));
            user.setUserEmail(rs.getString("email"));
            user.setUserPassword(rs.getString("password"));
            user.setUserStatus(rs.getString("status"));
        }
        
        return user;
    }
    
    
    public int register(LoginUser user) {
        String nameSql = "select login_name from e_user where login_name = ? ";
        
        String nameFromDB =  this.jdbcTemplate.query(nameSql, new ResultSetExtractor<String>() {

            @Override
            public String extractData(ResultSet rs) throws SQLException, DataAccessException {
                
                if(rs.next()) {
                    return rs.getString("login_name"); 
                }
                
                return null;
            }
            
        }, user.getLoginName());

        if(nameFromDB != null &&  !"".equals(nameFromDB)) {
            return 2;
        }
        
        String emailSql = "select login_name from e_user where email = ? ";
        String emailFromDB =  this.jdbcTemplate.query(emailSql, new ResultSetExtractor<String>() {

            @Override
            public String extractData(ResultSet rs) throws SQLException, DataAccessException {
                
                if(rs.next()) {
                    return rs.getString("login_name"); 
                }
                
                return null;
            }
            
        }, user.getUserEmail());

        if(emailFromDB != null &&  !"".equals(emailFromDB)) {
            return 3;
        }
        
        String sql = "INSERT INTO E_USER ( LOGIN_NAME,PASSWORD,EMAIL,creation_user, status) VALUES  ( ?, ?, ?, ?, ?)";
        String status = "1";
        String email = user.getUserEmail();

        this.jdbcTemplate.update(sql, user.getLoginName(), user.getUserPassword(), email , user.getLoginName(), status);
        
        return 1;
    }
    
    public Integer getValidationCode() {
        Random rand = new Random();
        Integer code = rand.nextInt(999999);
        logger.debug("" + code);
        return code;
    }
    
    public boolean validateEmail(String email, String vcode) {
        MailInfo info = new MailInfo();
        info.setSubject("Email Validation");
        info.setContent("Validation Code is " + vcode);
        String []emails = {
                email
        };
        info.setToAddress(Arrays.asList(emails));
        try {
            this.es.sendEmail(info);
        } catch (EmailException e) {
           
            e.printStackTrace();
            return false;
        }
        
        return true;
    }
    
    /**
     *
     * 0, invalid
     * 1, valid
     * 2, unactived
     * 3, locked
     * 4, haven't logined within three month.
     * 5, logic delete
     *
     * @param status
     * @return
     */
    public String getUserStatusDesc(String status) {
        String desc = "";
        
        switch(status) {
        case "0" :
            desc = "invalid";
            break;
        case "1" :
            desc = "valid";
            break;
        case "2" :
            desc = "inactived";
            break;
        case "3" :
            desc = "locked";
            break;
            
        case "4" :
            desc = "Not Login 3 Months";
            break;
        case "5" :
            desc = "logic delete";
            break;
        }
        
        return desc;
    }
    
}
